import os
import time

from selenium.webdriver.common import by
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait
from selenium import webdriver

from config import basedriver_config
from common_utils.logger_util import logger


class BaseDriverUtil:
    """
    封装selenium基础方法
    """

    def __init__(self, driver=None, url: str = basedriver_config.url):
        """
        初始化driver
        :param driver: 浏览器驱动
        """
        if driver:
            self.driver = driver
        else:
            # 使用反射获取浏览器驱动
            try:
                if hasattr(webdriver, basedriver_config.browser.title()):
                    self.driver = getattr(webdriver, basedriver_config.browser.title())()
                    self.driver.maximize_window()
                    self.driver.implicitly_wait(basedriver_config.implicitly_wait)
                    self.my_goto_url(url)
                    logger.info("打开浏览器：{0}, 并跳转到:{1}".format(basedriver_config.browser, url))
            except Exception as e:
                logger.error("{0}浏览器驱动不存在:{1}".format(basedriver_config.browser, e))
                raise Exception("{0}浏览器驱动不存在:{1}".format(basedriver_config.browser, e))

    def my_goto_url(self, url):
        """
        打开url
        :param url: 目标url
        :return
        """
        try:
            return self.driver.get(url)
        except Exception as e:
            logger.error(f"打开{url}失败:{e}")
            self.my_quit()

    def my_quit(self):
        """
        退出浏览器
        :return:
        """
        return self.driver.quit()

    def _my_wait_element_to_be_clickable(
            self,
            location: tuple[str, str],
            timeout: float = basedriver_config.timeout,
            poll: float = basedriver_config.poll):
        """
        等待元素可点击
        :param location: 元素定位   (“id”, "username")
        :param timeout: 等待时长    单位：秒
        :param poll: 等待间隔      单位：秒
        :return:     元素对象
        """
        try:
            # 使用反射获取元素定位方式
            locator_type = getattr(By, location[0].upper())
            new_location = (locator_type, location[1])

            logger.info(f"定位元素{location}成功")
            return WebDriverWait(self.driver, timeout, poll).until(ec.element_to_be_clickable(new_location))
        except Exception as e:
            logger.error(f"等待元素{location}可点击失败:{e}")
            self.my_quit()

    def my_locator(self, location):
        """
        定位元素
        :param location: 元素定位   ("id", "username")
        :return:     元素对象
        """
        try:
            # 使用反射获取元素定位方式
            locator_type = getattr(By, location[0].upper())
            new_location= (locator_type, location[1])
            # 等待元素可点击
            self._my_wait_element_to_be_clickable(new_location)
            logger.info(f"定位元素{new_location}成功")
            return self.driver.find_element(*new_location)
        except Exception as e:
            logger.error(f"定位元素{location}失败:{e}")
            self.my_quit()

    def my_input(self, location, value):
        """
        输入内容
        :param location: 元素定位   (“id”, "id")
        :param value: 输入内容
        :return:
        """
        try:
            self._my_wait_element_to_be_clickable(location)
            self.my_locator(location).send_keys(value)
        except Exception as e:
            logger.error(f"输入内容{value}失败:{e}")
            self.my_quit()

    def my_click(self, location: tuple[str, str]):
        """
        点击元素
        :param location: 元素定位   (By.ID, "id")
        :return:
        """
        try:
            self._my_wait_element_to_be_clickable(location)
            self.my_locator(location).click()
        except Exception as e:
            logger.error(f"点击元素{location}失败:{e}")
            self.my_quit()

    def my_get_text(self, location: tuple):
        """
        获取元素文本
        :param location: 元素定位   (By.ID, "id")
        :return:
        """
        try:
            return self.my_locator(location).text
        except Exception as e:
            logger.error(f"获取元素{location}文本失败:{e}")

    def my_screenshot(self, file_name: str):
        """
        截图
        :param file_name: 截图文件名
        :return:
        """
        try:
            file_path = basedriver_config.image_path
            if not os.path.exists(file_path):
                os.makedirs(file_path)
            file_name = file_path + "/" + file_name + ".png"
            self.driver.save_screenshot(file_name)
        except Exception as e:
            logger.error(f"截图失败:{e}")

if __name__ == '__main__':
    bs = BaseDriverUtil()
    bs.my_locator(("id", "kw"))
    bs.my_input(("id", "kw"), "selenium")
    time.sleep(2)
